home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / comm / misc / xqsrc931030.lzh / library / address.c next >
C/C++ Source or Header  |  1993-01-29  |  21KB  |  929 lines

  1. /*
  2.  *    Name:                address.c
  3.  *
  4.  * Description:    Routines for address manipulation
  5.  *
  6.  * Copyright:        1992-1993 by David Jones.
  7.  *
  8.  * Distribution:
  9.  *        This program is free software; you can redistribute it and/or modify
  10.  *        it under the terms of the GNU General Public License as published by
  11.  *        the Free Software Foundation; either version 2 of the License, or
  12.  *        (at your option) any later version.
  13.  *
  14.  *        This program is distributed in the hope that it will be useful,
  15.  *        but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *        GNU General Public License for more details.
  18.  *
  19.  *        You should have received a copy of the GNU General Public License
  20.  *        along with this program; if not, write to:
  21.  *
  22.  *                The Free Software Foundation        David Jones
  23.  *                675 Mass Ave                            6730 Tooney Drive
  24.  *                Cambridge, MA                            Orleans, Ontario
  25.  *                02139                                        K1C 6R4
  26.  *                USA                                        Canada
  27.  *
  28.  *    Usenet:    gnu@prep.ai.mit.edu                    dej@qpoint.ocunix.on.ca
  29.  *    Fidonet:                                                1:163/109.8
  30.  *
  31.  *        $Log: $
  32.  *
  33.  */
  34.  
  35. #include <exec/types.h>
  36. #include <string.h>
  37. #include "xferq.h"
  38. #include "xferqint.h"
  39. #include "xferq_pragmas.h"
  40. #include <utility/hooks.h>
  41. #include <proto/utility.h>
  42.  
  43. char *DefaultDomain, *DefaultZone, *DefaultPoint;
  44.  
  45. void InitAddress(void)
  46. /*
  47.  *    Does:    Initializes the default address values.  These are hard-coded
  48.  *            now, but will be read from a file eventually.
  49.  */
  50. {
  51.  
  52.     DefaultDomain = CopyString("Fidonet");
  53.     DefaultZone = CopyString("1");
  54.     DefaultPoint = CopyString("0");
  55. }
  56.  
  57.  
  58. struct NetAddress *GetTextAddress(char **strp)
  59. /*
  60.  *    In:    strp                Pointer to string to convert
  61.  *
  62.  * Does:    Attempts to convert an address in TEXT form.
  63.  */
  64. {
  65. char *p, *oldp;
  66. struct NetAddress *na;
  67. char *temp;
  68.  
  69.     /*
  70.      *    First character must be a caret.
  71.      */
  72.     p = *strp;
  73.     if (*p++ != '^') {
  74.         return NULL;
  75.     }
  76.     oldp = p;
  77.     /*
  78.      * Anything goes for content.
  79.      */
  80.     if (!GetAddrElement(&p, TRUE)) {
  81.         return NULL;
  82.     }
  83.     /*
  84.      * OMS needs a null-terminated string so make one.
  85.      */
  86.     temp = CopyStringN(oldp, p - oldp);
  87.     if (!temp) {
  88.         return NULL;
  89.     }
  90.     /*
  91.      * Create final address.
  92.      */
  93.     na = AllocObject(0, XQO_ADDRESS);
  94.     if (na) {
  95.         na->type = XQNT_TEXT;
  96.         na->addr.text = temp;
  97.         *strp = p;
  98.     }
  99.     else {
  100.         XfqDropObject(temp);
  101.     }
  102.     return na;
  103. }
  104.  
  105.  
  106. struct NetAddress *GetUucpAddress(char **strp)
  107. /*
  108.  *    In:    strp                Pointer to string to convert
  109.  *
  110.  * Does:    Attempts to convert an address in UUCP form.
  111.  */
  112. {
  113. char *p, *oldp;
  114. struct NetAddress *na;
  115. char *temp;
  116.  
  117.     p = *strp;
  118.     oldp = p;
  119.     /*
  120.      * Machine name must be non-numeric and no periods!
  121.      */
  122.     if (GetAddrElement(&p, FALSE) != ET_ALPHA) {
  123.         return NULL;
  124.     }
  125.     /*
  126.      * OMS needs a null-terminated string so make one.
  127.      */
  128.     temp = CopyStringN(oldp, p - oldp);
  129.     if (!temp) {
  130.         return NULL;
  131.     }
  132.     /*
  133.      * Create final address.
  134.      */
  135.     na = AllocObject(0, XQO_ADDRESS);
  136.     if (na) {
  137.         na->type = XQNT_UUCP;
  138.         na->addr.machine = temp;
  139.         *strp = p;
  140.     }
  141.     else {
  142.         XfqDropObject(temp);
  143.     }
  144.     return na;
  145. }
  146.  
  147.  
  148. struct NetAddress *GetFqdaAddress(char **strp)
  149. /*
  150.  *    In:    strp                Pointer to string to convert
  151.  *
  152.  * Does:    Attempts to convert an address in FQDA form.
  153.  */
  154. {
  155. char *p, *oldp;
  156. struct NetAddress *na;
  157. char *temp;
  158.  
  159.     p = *strp;
  160.     oldp = p;
  161.     while (TRUE) {
  162.         /*
  163.          * Each component must be non-numeric and no periods!
  164.          */
  165.         if (GetAddrElement(&p, FALSE) != ET_ALPHA) {
  166.             return NULL;
  167.         }
  168.         /*
  169.          *    If parse stopped at a period, then go for more.
  170.          */
  171.         if (*p != '.') {
  172.             break;
  173.         }
  174.         p++;
  175.     }
  176.     /*
  177.      * OMS needs a null-terminated string so make one.
  178.      */
  179.     temp = CopyStringN(oldp, p - oldp);
  180.     if (!temp) {
  181.         return NULL;
  182.     }
  183.     /*
  184.      * Create final address.
  185.      */
  186.     na = AllocObject(0, XQO_ADDRESS);
  187.     if (na) {
  188.         na->type = XQNT_FQDA;
  189.         na->addr.fqda = temp;
  190.         *strp = p;
  191.     }
  192.     else {
  193.         XfqDropObject(temp);
  194.     }
  195.     return na;
  196. }
  197.  
  198.  
  199. struct NetAddress *GetFidoAddress(char **strp, struct NetAddress *base,
  200.     int mand, int opt)
  201. /*
  202.  *    In:    strp                Pointer to string to parse
  203.  *            base                Base address to use as model
  204.  *            mand                Mandatory flags
  205.  *            opt                Optional flags
  206.  *
  207.  * Does:    Attempts to parse a Fidonet address.
  208.  */
  209. {
  210. char preDelim, postDelim;
  211. struct NetAddress *na;
  212. char *p, *oldp, *elem;
  213. int type;
  214.  
  215.     postDelim = 0;
  216.     p = *strp;
  217.     if (base) {
  218.         na = DupObject(base);
  219.     }
  220.     else {
  221.         na = AllocObject(0, XQO_ADDRESS);
  222.     }
  223.     if (!na) {
  224.         return NULL;
  225.     }
  226.     na->type = XQNT_FIDO;
  227.     opt &= XQADDR_FIDO;
  228.     mand &= XQADDR_FIDO;
  229.     while (TRUE) {
  230.         preDelim = postDelim;
  231.         oldp = p;
  232.         type = GetAddrElement(&p, FALSE);
  233.         postDelim = *p;
  234.         if (!type) {
  235.             XfqDropObject(na);
  236.             return NULL;
  237.         }
  238.         elem = CopyStringN(oldp, p - oldp);
  239.         if (opt == XQADDR_DOMAIN || postDelim == '#' || preDelim == '@') {
  240.             /*
  241.              * domain
  242.              *
  243.              * Replace the domain name, dropping old one if necessary.
  244.              * If element type is illegal, then the DropObject(na) drops
  245.              * the new element too.
  246.              */
  247.             XfqDropObject(na->addr.fido.domain);
  248.             na->addr.fido.domain = elem;
  249.             if (type != ET_ALPHA || !(opt & XQADDR_DOMAIN)) {
  250.                 XfqDropObject(na);
  251.                 return NULL;
  252.             }
  253.             mand &= ~XQADDR_DOMAIN;
  254.             if (postDelim == '#') {
  255.                 p++;
  256.             }
  257.             else {
  258.                 break;
  259.             }
  260.         }
  261.         else if (opt == XQADDR_ZONE || postDelim == ':') {
  262.             /* zone */
  263.             XfqDropObject(na->addr.fido.zone);
  264.             na->addr.fido.zone = elem;
  265.             if (type != ET_NUMBER || !(opt & XQADDR_ZONE)) {
  266.                 XfqDropObject(na);
  267.                 return NULL;
  268.             }
  269.             mand &= ~XQADDR_ZONE;
  270.             if (postDelim == ':') {
  271.                 p++;
  272.             }
  273.             else {
  274.                 break;
  275.             }
  276.         }
  277.         else if (opt == XQADDR_NET || postDelim == '/' || preDelim == ':') {
  278.             /* net */
  279.             XfqDropObject(na->addr.fido.net);
  280.             na->addr.fido.net = elem;
  281.             if (type != ET_NUMBER || !(opt & XQADDR_NET)) {
  282.                 XfqDropObject(na);
  283.                 return NULL;
  284.             }
  285.             mand &= ~XQADDR_NET;
  286.             if (postDelim == '/') {
  287.                 p++;
  288.             }
  289.             else {
  290.                 break;
  291.             }
  292.         }
  293.         else if (opt == XQADDR_NODE ||  preDelim == '/') {
  294.             /* node */
  295.             XfqDropObject(na->addr.fido.node);
  296.             na->addr.fido.node = elem;
  297.             if (type != ET_NUMBER || !(opt & XQADDR_NODE)) {
  298.                 XfqDropObject(na);
  299.                 return NULL;
  300.             }
  301.             mand &= ~XQADDR_NODE;
  302.             if (postDelim == '.' || postDelim == '@') {
  303.                 p++;
  304.             }
  305.             else {
  306.                 break;
  307.             }
  308.         }
  309.         else if (opt == XQADDR_POINT || preDelim == '.') {
  310.             /* point */
  311.             XfqDropObject(na->addr.fido.point);
  312.             na->addr.fido.point = elem;
  313.             if (type != ET_NUMBER || !(opt & XQADDR_POINT)) {
  314.                 XfqDropObject(na);
  315.                 return NULL;
  316.             }
  317.             mand &= ~XQADDR_POINT;
  318.             if (postDelim == '@') {
  319.                 p++;
  320.             }
  321.             else {
  322.                 break;
  323.             }
  324.         }
  325.         else {
  326.             XfqDropObject(na);
  327.             return NULL;
  328.         }
  329.     }
  330.     /* end of address */
  331.     if (mand) {
  332.         XfqDropObject(na);
  333.         return NULL;
  334.     }
  335.     else {
  336.         *strp = p;
  337.         CanonAddress(na);
  338.         return na;
  339.     }
  340. }
  341.  
  342.  
  343. struct NetAddress *__saveds __asm LIBGetAddress(register __a0 char *string,
  344.     register __a1 struct NetAddress *addr,
  345.     register __a2 struct TagItem *tags)
  346. /*
  347.  *    In:    string    A0        Pointer to string to convert
  348.  *            addr        A1        Template for converted address
  349.  *            tags        A2        Taglist controlling operation
  350.  *
  351.  * Does:    Replaces the elements of addr with new values based on the
  352.  *            input string.  The user flags indicate which types of input
  353.  *            are valid, and may be used to resolve ambiguous situations.
  354.  *
  355.  *            Valid tags are:
  356.  *                XQ_EndPos        Write a pointer to the first illegal char
  357.  *                                    into data field.
  358.  *                XQ_Mandatory    Data is bitset of mandatory fields
  359.  *                XQ_Optional        Data is bitset of optional fields
  360.  *                XQ_SpaceDelim    TRUE if spaces are permitted.
  361.  */
  362. {
  363. struct NetAddress *na;
  364. int mand, opt;
  365. char *p, *oldp, *atp;
  366. char **endPos;
  367. BOOL spaceDelim;
  368. char *userName;
  369. ULONG *errp;
  370.  
  371.     mand = GetTagData(XQ_Mandatory, 0, tags);
  372.     opt = GetTagData(XQ_Optional, 0, tags);
  373.     spaceDelim = GetTagData(XQ_SpaceDelim, TRUE, tags);
  374.     
  375.     /*
  376.      *    atp holds pointer to stuff after username.
  377.      */
  378.     p = string;
  379.     userName = NULL;
  380.     oldp = p;
  381.     if (GetAddrElement(&p, TRUE) == ET_ALPHA) {
  382.         /*
  383.          *    Got what might be a user name.  If next char is '@' then
  384.          * make the user name.
  385.          */
  386.         atp = p;
  387.         if (spaceDelim && *p == ' ') {
  388.             atp++;
  389.         }
  390.         if (*atp == '@') {
  391.             userName = CopyStringN(oldp, p - oldp);
  392.             if (!userName) {
  393.                 return NULL;
  394.             }
  395.             atp++;
  396.             if (spaceDelim && *atp == ' ') {
  397.                 atp++;
  398.             }
  399.         }
  400.     }
  401.     if (!userName) {
  402.         atp = string;
  403.     }
  404.     na = NULL;
  405.     p = atp;
  406.     if (addr) {
  407.         switch (addr->type) {
  408.         case XQNT_FIDO:
  409.             na = GetFidoAddress(&p, addr, mand, opt);
  410.             break;
  411.         case XQNT_UUCP:
  412.             na = GetUucpAddress(&p);
  413.             break;
  414.         case XQNT_FQDA:
  415.             na = GetFqdaAddress(&p);
  416.             break;
  417.         case XQNT_TEXT:
  418.             na = GetTextAddress(&p);
  419.             break;
  420.         }
  421.     }
  422.     if (!na) {
  423.         if (opt & XQADDR_FIDO) {
  424.             p = atp;
  425.             na = GetFidoAddress(&p, addr, mand, opt);
  426.         }
  427.         if (!na && (opt & XQADDR_MACHINE)) {
  428.             p = atp;
  429.             na = GetUucpAddress(&p);
  430.         }
  431.         if (!na && (opt & XQADDR_FQDA)) {
  432.             p = atp;
  433.             na = GetFqdaAddress(&p);
  434.         }
  435.         if (!na && (opt & XQADDR_TEXT)) {
  436.             p = atp;
  437.             na = GetTextAddress(&p);
  438.         }
  439.     }
  440.     if (na) {
  441.         na->userName = userName;
  442.     }
  443.     else {
  444.         errp = PeekError();
  445.         if (*errp != XQERROR_NOMEM) {
  446.             *errp = XQERROR_BADADR;
  447.         }
  448.         XfqDropObject(userName);
  449.     }
  450.     endPos = (char **)GetTagData(XQ_EndPos, NULL, tags);
  451.     if (endPos) {
  452.         *endPos = p;
  453.     }
  454.     SetErrorTags(tags);
  455.     return na;
  456. }
  457.  
  458.  
  459. LONG StrAECmp(char *left, char *right)
  460. /*
  461.  *    In:    left, right        Pointers to items to compare
  462.  *
  463.  * Does:    Compares two address elements and returns less/greater/equal.
  464.  */
  465. {
  466.  
  467.     if (!left) {
  468.         return (right != NULL);
  469.     }
  470.     else if (!right) {
  471.         return 1;
  472.     }
  473.     else {
  474.         return Stricmp(left, right);
  475.     }
  476. }
  477.  
  478.  
  479. LONG NumAECmp(char *left, char *right)
  480. /*
  481.  *    In:    left, right        Pointers to items to compare
  482.  *
  483.  * Does:    Compares two numeric address elements and returns delta.
  484.  */
  485. {
  486. LONG nleft, nright;
  487.  
  488.     nleft = nright = 0;
  489.     if (left) {
  490.         GetNumber(left, 10, 5, &nleft);
  491.     }
  492.     if (right) {
  493.         GetNumber(right, 10, 5, &nright);
  494.     }
  495.     return nleft - nright;
  496. }
  497.  
  498.  
  499. LONG SimpleCmpAddress(struct NetAddress *left, struct NetAddress *right,
  500.     int mand)
  501. /*
  502.  *    In:    left, right        Pointers to addresses to compare
  503.  *            mand                Bit mask of mandatory items
  504.  *
  505.  * Does:    Compares two addresses and returns a delta based on the
  506.  *            difference.
  507.  */
  508. {
  509. LONG delta;
  510.  
  511.     delta = left->type - right->type;
  512.     if (delta) {
  513.         return delta;
  514.     }
  515.     switch (left->type) {
  516.     case XQNT_UUCP:
  517.             return StrAECmp(left->addr.machine, right->addr.machine);
  518.     case XQNT_FQDA:
  519.             return StrAECmp(left->addr.fqda, right->addr.fqda);
  520.     case XQNT_TEXT:
  521.             return StrAECmp(left->addr.text, right->addr.text);
  522.     case XQNT_FIDO:
  523.         if (mand & XQADDR_DOMAIN) {
  524.             delta = StrAECmp(left->addr.fido.domain, right->addr.fido.domain);
  525.             if (delta) {
  526.                 return delta;
  527.             }
  528.         }
  529.         if (mand & XQADDR_ZONE) {
  530.             delta = NumAECmp(left->addr.fido.zone, right->addr.fido.zone);
  531.             if (delta) {
  532.                 return delta;
  533.             }
  534.         }
  535.         if (mand & XQADDR_NET) {
  536.             delta = NumAECmp(left->addr.fido.net, right->addr.fido.net);
  537.             if (delta) {
  538.                 return delta;
  539.             }
  540.         }
  541.         if (mand & XQADDR_NODE) {
  542.             delta = NumAECmp(left->addr.fido.node, right->addr.fido.node);
  543.             if (delta) {
  544.                 return delta;
  545.             }
  546.         }
  547.         if (mand & XQADDR_POINT) {
  548.             return NumAECmp(left->addr.fido.point, right->addr.fido.point);
  549.         }
  550.         return 0;
  551.     }
  552. }
  553.  
  554.  
  555. LONG __saveds __asm LIBCmpAddress(register __a0 void *left,
  556.     register __a1 void *right,
  557.     register __a2 struct TagItem *tags)
  558. /*
  559.  *    In:    left        A0        "Left" address or session
  560.  *            right        A1        "Right" address or session
  561.  *            tags        A2        Taglist controlling operation
  562.  * 
  563.  * Does:    Compares left and right.  Returns:
  564.  *                >0    if left > right
  565.  *                 0    if left = right
  566.  *                <0 if left < right
  567.  *
  568.  *            Either left or right may be a session; in this case equality
  569.  *            is returned if any address in left is equivalent to any address
  570.  *            in right.
  571.  *
  572.  *            Valid tags are:
  573.  *                XQ_Mandatory    Indicates fields that are to be used in
  574.  *                                    comparison (default all).
  575.  */
  576. {
  577. int mand,result;
  578.  
  579.     mand = GetTagData(XQ_Mandatory, XQADDR_ALLBUTUSER, tags);
  580.     result = SimpleCmpAddress(left, right, mand);
  581.     return result;
  582. }
  583.  
  584.  
  585. struct NetAddress *__saveds __asm LIBMap(
  586.     register __a0 struct NetAddress *addr,
  587.     register __a1 struct TagItem *tags)
  588. /*
  589.  *    In:    addr        A0        Address to map
  590.  *            tags        A1        Taglist controlling operation
  591.  *
  592.  * Does:    Applies maps according to the tags to return a new address.
  593.  *            Valid tags are:
  594.  *                XQ_MapForward    Apply the map in the forward direction
  595.  *                XQ_MapReverse    Apply the map in the reverse direction
  596.  */
  597. {
  598.  
  599.     return NULL;
  600. }
  601.  
  602.  
  603. ULONG __saveds __asm LIBFilter(register __a0 void *object,
  604.     register __a1 struct TagItem *tags)
  605. /*
  606.  *    In:    object    A0        Address or session to filter
  607.  *            tags        A1        Taglist controlling operation
  608.  *
  609.  * Does:    Tests the session or address against the filter condition.
  610.  *            Returns TRUE if it passes, FALSE otherwise.  Valid tags are:
  611.  *
  612.  *                XQ_MapForward    Test against the left part of a map.
  613.  *                XQ_MapReverse    Test against the right part of a map.
  614.  *                XQ_Filter        Test against a filter
  615.  *                XQ_Inclusive    If TRUE, all objects in the session must pass
  616.  *                                    the filter.  Otherwise, only one need pass.
  617.  */
  618. {
  619.  
  620.     return FALSE;
  621. }
  622.  
  623.  
  624. char *SimplePutAddress(struct NetAddress *na, int mand, int opt,
  625.     BOOL spaceDelim)
  626. /*
  627.  *    In:    na                    Address to print
  628.  *            mand                Bit mask of mandatory fields
  629.  *            opt                Bit mask of optional fields
  630.  *            spaceDelim        TRUE to insert spaces in Fido
  631.  *
  632.  * Does:    Creates a string and puts the given address in it.
  633.  */
  634. {
  635. char *str;
  636. int adrLen;
  637. int partLen;
  638.  
  639.     str = AllocObject(20, XQO_STRING);
  640.     if (!str) {
  641.         return NULL;
  642.     }
  643.     *str = '\0';
  644.     adrLen = 0;
  645.     if (na->userName) {
  646.         partLen = strlen(na->userName);
  647.         str = NeedString(str, partLen + 4);    /* make room for ' @ ' */
  648.         if (!str) {
  649.             return NULL;
  650.         }
  651.         strcpy(str, na->userName);
  652.         adrLen = partLen;
  653.         if (na->addr.machine || na->addr.fqda || na->addr.text ||
  654.             na->addr.fido.domain || na->addr.fido.zone ||
  655.             na->addr.fido.net || na->addr.fido.node || na->addr.fido.point) {
  656.             if (na->type == XQNT_FIDO && spaceDelim) {
  657.                 strcpy(str + adrLen, " @ ");
  658.                 adrLen += 3;
  659.             }
  660.             else {
  661.                 strcpy(str + adrLen, "@");
  662.                 adrLen++;
  663.             }
  664.         }
  665.     }
  666.     switch (na->type) {
  667.     case XQNT_TEXT:
  668.         partLen = strlen(na->addr.text);
  669.         str = NeedString(str, partLen + 2);
  670.         if (str) {
  671.             str[partLen] = '^';
  672.             strcpy(str + adrLen, na->addr.text);
  673.         }
  674.         return str;
  675.     case XQNT_FQDA:
  676.         partLen = strlen(na->addr.fqda);
  677.         str = NeedString(str, partLen + 1);
  678.         if (str) {
  679.             strcpy(str + adrLen, na->addr.fqda);
  680.         }
  681.         return str;
  682.     case XQNT_UUCP:
  683.         partLen = strlen(na->addr.machine);
  684.         str = NeedString(str, partLen + 1);
  685.         if (str) {
  686.             strcpy(str + adrLen, na->addr.machine);
  687.         }
  688.         return str;
  689.     case XQNT_FIDO:
  690.         /*
  691.          *    Determine which fields to print out.  mand's bits are set
  692.          * to indicate which fields must be printed.
  693.          */
  694.         if (opt & XQADDR_DOMAIN && na->addr.fido.domain &&
  695.             Stricmp(na->addr.fido.domain, DefaultDomain)) {
  696.             mand |= XQADDR_DOMAIN;
  697.         }
  698.         if (opt & XQADDR_ZONE && na->addr.fido.zone &&
  699.             Stricmp(na->addr.fido.zone, DefaultZone)) {
  700.             mand |= XQADDR_ZONE;
  701.         }
  702.         if (opt & XQADDR_NET && na->addr.fido.net &&
  703.             Stricmp(na->addr.fido.net, "0") &&
  704.             Stricmp(na->addr.fido.net, "-1")) {
  705.             mand |= XQADDR_NET;
  706.         }
  707.         if (opt & XQADDR_NODE && na->addr.fido.node &&
  708.             Stricmp(na->addr.fido.node, "0") &&
  709.             Stricmp(na->addr.fido.node, "-1")) {
  710.             mand |= XQADDR_NODE;
  711.         }
  712.         if (opt & XQADDR_POINT && na->addr.fido.point &&
  713.             Stricmp(na->addr.fido.point, "0")) {
  714.             mand |= XQADDR_POINT;
  715.         }
  716.         if (opt & XQADDR_ATDOMAIN && na->addr.fido.domain &&
  717.             Stricmp(na->addr.fido.domain, DefaultDomain)) {
  718.             mand |= XQADDR_ATDOMAIN;
  719.         }
  720.         /*
  721.          * Protection: don't attempt to output fields that don't exist.
  722.          */
  723.         if (!na->addr.fido.domain) {
  724.             mand &= ~(XQADDR_DOMAIN | XQADDR_ATDOMAIN);
  725.         }
  726.         if (!na->addr.fido.zone) {
  727.             mand &= ~XQADDR_ZONE;
  728.         }
  729.         if (!na->addr.fido.net) {
  730.             mand &= ~XQADDR_NET;
  731.         }
  732.         if (!na->addr.fido.node) {
  733.             mand &= ~XQADDR_NODE;
  734.         }
  735.         if (!na->addr.fido.point) {
  736.             mand &= ~XQADDR_POINT;
  737.         }
  738.         /*
  739.          * Print required fields.
  740.          */
  741.         if (mand & XQADDR_DOMAIN) {
  742.             partLen = strlen(na->addr.fido.domain);
  743.             str = NeedString(str, partLen + 2);
  744.             if (!str) {
  745.                 return NULL;
  746.             }
  747.             strcpy(str + adrLen, na->addr.fido.domain);
  748.             adrLen += partLen;
  749.             if (mand & (XQADDR_ZONE | XQADDR_NET)) {
  750.                 str[adrLen++] = '#';
  751.             }
  752.         }
  753.         if (mand & XQADDR_ZONE) {
  754.             partLen = strlen(na->addr.fido.zone);
  755.             str = NeedString(str, partLen + 2);
  756.             if (!str) {
  757.                 return NULL;
  758.             }
  759.             strcpy(str + adrLen, na->addr.fido.zone);
  760.             adrLen += partLen;
  761.             if (mand & XQADDR_NET) {
  762.                 str[adrLen++] = ':';
  763.             }
  764.         }
  765.         if (mand & XQADDR_NET) {
  766.             partLen = strlen(na->addr.fido.net);
  767.             str = NeedString(str, partLen + 2);
  768.             if (!str) {
  769.                 return NULL;
  770.             }
  771.             strcpy(str + adrLen, na->addr.fido.net);
  772.             adrLen += partLen;
  773.             if (mand & XQADDR_NODE) {
  774.                 str[adrLen++] = '/';
  775.             }
  776.         }
  777.         if (mand & XQADDR_NODE) {
  778.             partLen = strlen(na->addr.fido.node);
  779.             str = NeedString(str, partLen + 2);
  780.             if (!str) {
  781.                 return NULL;
  782.             }
  783.             strcpy(str + adrLen, na->addr.fido.node);
  784.             adrLen += partLen;
  785.             if (mand & XQADDR_POINT) {
  786.                 str[adrLen++] = '.';
  787.             }
  788.         }
  789.         if (mand & XQADDR_POINT) {
  790.             partLen = strlen(na->addr.fido.point);
  791.             str = NeedString(str, partLen + 2);
  792.             if (!str) {
  793.                 return NULL;
  794.             }
  795.             strcpy(str + adrLen, na->addr.fido.point);
  796.             adrLen += partLen;
  797.             if (mand & XQADDR_ATDOMAIN) {
  798.                 str[adrLen++] = '@';
  799.             }
  800.         }
  801.         if (na->addr.fido.domain && (mand & XQADDR_ATDOMAIN)) {
  802.             partLen = strlen(na->addr.fido.domain);
  803.             str = NeedString(str, partLen + 2);
  804.             if (!str) {
  805.                 return NULL;
  806.             }
  807.             strcpy(str + adrLen, na->addr.fido.domain);
  808.         }
  809.     }
  810.     return str;
  811. }
  812.  
  813.  
  814. struct PutAddrData {
  815.     struct Hook hook;
  816.     char **array;
  817.     char *line;
  818.     struct NetAddress *last;
  819.     struct NetAddress *diff;
  820.     short lineSize, mand, opt;
  821.     BOOL delta, spaceDelim;
  822. };
  823.  
  824.  
  825. BOOL __asm PutSessAddress(register __a0 struct Hook *hook,
  826.     register __a2 struct NetAddress *addr,
  827.     register __a1 struct TagItem *tags)
  828. /*
  829.  *    In:    hook        A0        Pointer to hook/data structure
  830.  *            addr        A2        Pointer to address to print
  831.  *            tags        A1        Tag list passed to PutAddress (not used)
  832.  *
  833.  * Does:    Writes one address of the session into the array.
  834.  */
  835. {
  836.  
  837.     return FALSE;
  838. }
  839.         
  840.  
  841. char *__saveds __asm LIBPutAddress(register __a0 void *object,
  842.     register __a1 struct TagItem *tags)
  843. /*
  844.  *    In:    object    A0        Pointer to address/session to output
  845.  *            tags        A1        Taglist controlling operation
  846.  *
  847.  * Does:    Returns a string containing a printable form of the address.
  848.  *            Valid tags are:
  849.  *
  850.  *                XQ_Mandatory    Data is fields that must be printed
  851.  *                XQ_Optional        Data is fields that are printed if nonempty
  852.  *                XQ_LineSize        This tag is used when a session is passed in.
  853.  *                                    All addresses in the session are output in
  854.  *                                    a single string whose maximum length is given
  855.  *                                    by this tag.  Function returns array of these
  856.  *                                    strings.
  857.  *                XQ_Delta            If TRUE, then the differences between the
  858.  *                                    current and previous addresses are used in
  859.  *                                    determining if optional fields should be output.
  860.  *                XQ_SpaceDelim    If TRUE, then spaces are output around '@'
  861.  *                                    separating user name and Fidonet address.
  862.  */
  863. {
  864. struct PutAddrData pad;
  865. char *str;
  866.  
  867.     pad.mand = GetTagData(XQ_Mandatory, 0, tags);
  868.     pad.opt = GetTagData(XQ_Optional, 0, tags);
  869.     pad.spaceDelim = GetTagData(XQ_SpaceDelim, TRUE, tags);
  870.     
  871.     if (ObjectType(object) == XQO_ADDRESS) {
  872.         str = SimplePutAddress(object, pad.mand, pad.opt, pad.spaceDelim);
  873.         SetErrorTags(tags);
  874.         return str;
  875.     }
  876.     /*
  877.     else {
  878.         pad.delta = GetTagData(XQ_Delta, FALSE, tags);
  879.         pad.lineSize = GetTagData(XQ_LineSize, 79, tags);
  880.         if (pad.delta) {
  881.             pad.diff = AllocObject(XQO_ADDRESS, NULL);
  882.             if (!pad.diff) {
  883.                 return NULL;
  884.             }
  885.         }
  886.         pad.hook.h_Entry = PutSessAddress;
  887.         pad.last = NULL;
  888.         pad.array = NULL;
  889.         pad.line = NULL;
  890.         XfqWalkSessionCallBackTags(object,
  891.             XQ_CallBack, &pad.hook,
  892.             TAG_DONE);
  893.         SetErrorTags(tags);
  894.         return (char *)pad.array;
  895.     } */
  896.     Error(XQERROR_BADOBJECT);
  897.     return NULL;
  898. }
  899.  
  900.  
  901. BOOL CanonAddress(struct NetAddress *na)
  902. /*
  903.  *    In:    na                    User-supplied address
  904.  *
  905.  *    Does:    This function is a kludge that ensures that addresses conform
  906.  *            to certain style guidelines for queue files.  The function
  907.  *            returns an address derived from the given address through the
  908.  *            following transformations:
  909.  *
  910.  *            FIDO            z:n/f -> Fidonet#z:n/f.0
  911.  */
  912. {
  913.  
  914.     if (na->type == XQNT_FIDO) {
  915.         if (!na->addr.fido.domain || !strcmp(na->addr.fido.domain, "")) {
  916.             na->addr.fido.domain = XfqCopyObject(DefaultDomain);
  917.         }
  918.         if (!na->addr.fido.zone || !strcmp(na->addr.fido.zone, "")) {
  919.             na->addr.fido.zone = XfqCopyObject(DefaultZone);
  920.         }
  921.         if (!na->addr.fido.point || !strcmp(na->addr.fido.point, "")) {
  922.             na->addr.fido.point = XfqCopyObject(DefaultPoint);
  923.         }
  924.     }
  925.     return TRUE;
  926. }
  927.  
  928.  
  929.